package com.net.Thread;

class Test implements Runnable
{
   Object obj1;
   Object obj2;
   
   Test(Object obj1,Object obj2)
   {
	   this.obj1 = obj1;
	   this.obj2 = obj2;
   }
	
	
	@Override
	public void run() 
	{
		String name = Thread.currentThread().getName();
		System.out.println(name +"aquiring lock on " +obj1);
		synchronized (obj1)
		{
			System.out.println(name + "aquired lock on " +obj1);
			work();
			
			System.out.println(name + "aquiring lock on " +obj2);
			
			synchronized (obj2) 
			{
				System.out.println(name + " acquired lock on  " +obj2);
				work();
			}
			System.out.println("released lock on " +obj2);
		}
		
	}
	
	public void work()
	{
		try
		{
			Thread.sleep(300);
		} catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}
	
}









public class DeadLockTest {

	public static void main(String[] args) throws InterruptedException 
	{
		Object obj1 = new Object();
		Object obj2 = new Object();
		Object obj3 = new Object();
		
		Thread t1 = new Thread(new Test(obj1, obj2), "t1");
		Thread t2 = new Thread(new Test(obj1, obj3), "t2");
		Thread t3 = new Thread(new Test(obj2, obj3), "t3");
		
		t1.start();
		Thread.sleep(5000);
		
		t2.start();
		Thread.sleep(5000);
		
		t3.start();
		Thread.sleep(5000);
		
		

	}

}
